package com.example.onlinemonitoring.comCenter;

import com.example.onlinemonitoring.Util.CRC16;
import com.example.onlinemonitoring.Util.CommPortManager;
import com.example.onlinemonitoring.Util.HexUtil;
import com.example.onlinemonitoring.model.Bxsusbpdsensor;
import com.example.onlinemonitoring.model.Byqpdsensor;
import com.example.onlinemonitoring.model.Mxcwsensor;
import com.example.onlinemonitoring.model.common.MyResult;
import com.example.onlinemonitoring.model.Bxsusbpdhistory;
import com.example.onlinemonitoring.model.Appdevice;
import com.example.onlinemonitoring.serviceImpl.BxsusbpdsensorServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.context.annotation.Scope;
import java.util.Random;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * BxsusbpdCom
 * 便携式局放
 * 用于接收和发送便携式局放设备数据消息
 * @author zzc
 * @date 2023-08-28
 */
@Service("bxsusbpdCom")
@Scope("prototype")
public class BxsusbpdCom extends CommPortManager {
    int recvfalg = 0;
    String cstr = "";
    Process pro=null;
    Random rand = new Random();
    String currentPath="D:\\变电站在线监测\\usbpdman.exe";
    //String currentPath = System.getProperty("user.dir") + "\\usbpdman.exe";
        @Autowired
        private BxsusbpdsensorServiceImpl bxsusbpdsensorServiceImpl;

/**
 * 接收便携式局放设备数据消息
 * 
 * @param str 数据消息
 * 
 */
        @Override
        public void receiveData(String str) {
            try {
                str = str.toUpperCase();//转大写字符
                setText(str);//打印数据
                //条件判断自己写
                String addrstr = str.substring(0, 2);//设备地址
                Integer addrint = parseHex4(addrstr);

                reSend[addrint] = 0;//重发标记
                addrindex++;//当前地址
                int chargecount=0;
                float chargephase=0;
                float chargeamount = 0;
                String DType = "";
                float dischargecoef = 0.045f;
                int Devicegroup =0;
                if(ad.getCommunicationmode()==1)
                {
                    Devicegroup = ad.getDevicegroup();
                    if (str.length()<12||Devicegroup!=addrint)
                    return;




                   // String str_path="D:\\变电站在线监测\\usbpdman.exe";
                    float delay = 2 / ad.getBaudrate()*1000;
                    Runtime rt = Runtime.getRuntime();
                    pro=rt.exec(currentPath);
                    Thread.sleep(400 + (int)delay);
                    if(pro.isAlive())
                    {
                        Thread.sleep(1000);
                    }
                }

                Bxsusbpdsensor pdsensor = new Bxsusbpdsensor();
                pdsensor.setStationid(ad.getStationid());
                pdsensor.setDeviceaddr(addrint);
                pdsensor.setDevicegroup(ad.getDevicegroup());
                MyResult<Bxsusbpdsensor> res = bxsusbpdsensorServiceImpl.getList(pdsensor);
                for (int i = 0; i < res.getCount(); i++) {
                    
                    //查询对象
                    Bxsusbpdsensor record = res.getData().get(i);
                    if (record == null) {
                        setText("当前数据库无监测点：设备地址" + 1 + "的监测点" + (i+1)+ " ！ 请先添加该监测点！");
                        return;
                    }
                    if(record.getInuse()==0)
                    return;

                    pdsensor.setPointaddr(record.getPointaddr());
                    chargecount = isnull(record.getLastchargecount());
                    pdsensor.setLastchargecount(chargecount);
                    chargephase = isnull(record.getLastphase());
                    dischargecoef = isnull(record.getDischargecoef());
                    chargeamount = isnull(record.getLastdischargeamount());
                    pdsensor.setLastdischargeamount(chargeamount);
                    int iType = 4;
                    DType = isnull(record.getLastdischargetype());

                    for(int j=0;j<5;j++)
                    {
                        if(DType.compareTo(DischargeType[j])==0)
                        iType = j;
                    }

                    //pdsensor.setLastchargeamount2(chargeamount2);
                    Date dt =new Date();
                    Date dt2 = record.getLastdatatime();

                    //if(dt.compareTo(dt2)>0)
                        AddAndUpdate(record,pdsensor);
                    if(ad.getCommunicationmode()==1)
                    {
                        if(i==0)
                        {
                            int ichargeamount = (int)chargeamount;
                            cstr = String.format("%02x05%02x%04x%02x%04x%02x147B3F0000004228999A00000000C226C28F461A%04x", ad.getAddrmin(),Devicegroup,chargephase,rand.nextInt(8),chargecount,iType,ichargeamount);
                            cstr = cstr + CRC16.calcCrc16(cstr);
                            Send(cstr);
                        } 
                    }

                }

            } catch (Exception ex) {
                ex.printStackTrace();
                setText("从设备返回的数据有误！请检查串口！");
            }
        }

        @Transactional
        private void AddAndUpdate(Bxsusbpdsensor record,Bxsusbpdsensor pdsensor) {
            int alarmLevel = 0;// 报警等级
            String alarmMessage = "";// 报警消息
            if (
                // record.getDischargecountalarmvalue() == null ||
                // record.getDischargecountalarmrelievevalue() == null ||
                // record.getDischargecountwarnvalue() == null ||
                // record.getDischargecountwarnrelievevalue() == null||
                record.getDischargeamountalarmvalue() == null ||
                record.getDischargeamountalarmrelievevalue() == null ||
                record.getDischargeamountwarnvalue() == null ||
                record.getDischargeamountwarnrelievevalue() == null 
        ) {
            setText("设备地址" + record.getDeviceaddr() + " 未设置报警值！");
            return;
        }        
        List<Integer> array = new ArrayList<>();
        float chargeamountmax=isnull(pdsensor.getLastdischargeamount());
        //String[] chargeamount = pdsensor.getLastchargeamountdate().split(",");
        //int length = chargeamount.length;
        // double[] f_chargeamount = new double[length];
        // for (int i = 0; i < length; i++) {
        //     f_chargeamount[i] = Double.parseDouble(chargeamount[i]);
        //     if(chargeamountmax>f_chargeamount[i])
        //         chargeamountmax = (float)f_chargeamount[i];
        // }
        pdsensor.setLastchargemountalarmstatus(
            GetAlarmStatus(isnull(chargeamountmax), isnull(record.getDischargeamountalarmvalue()),
                    isnull(record.getDischargeamountalarmrelievevalue()), isnull(record.getDischargeamountwarnvalue()),
                    isnull(record.getDischargeamountwarnrelievevalue()),
                    isnull(record.getLastchargemountalarmstatus()), true, "放电量", record.getDevicegroup(), record.getDeviceaddr(),
                    record.getPointname(),record.getPointaddr()));
        alarmMessage += GetAlarmMessage(pdsensor.getLastchargemountalarmstatus(), "放电量");
        array.add(pdsensor.getLastchargemountalarmstatus());
        // pdsensor.setLastchargemountalarmstatus(
        //     GetAlarmStatus(isnull(pdsensor.getLastchargeamount2()), isnull(record.getDischargeamountalarmvalue()),
        //             isnull(record.getDischargeamountalarmrelievevalue()), isnull(record.getDischargeamountwarnvalue()),
        //             isnull(record.getDischargeamountwarnrelievevalue()),
        //             isnull(record.getLastchargemountalarmstatus()), true, "放电量2", record.getDevicegroup(), record.getDeviceaddr(),
        //             record.getPointname()));
        // alarmMessage += GetAlarmMessage(pdsensor.getLastchargemountalarmstatus(), "放电量2");
        // array.add(pdsensor.getLastchargemountalarmstatus());

        // pdsensor.setLastchargecountalarmstatus(
        //     GetAlarmStatus(isnull(pdsensor.getLastchargecount()), isnull(record.getDischargecountalarmvalue()),
        //             isnull(record.getDischargecountalarmrelievevalue()), isnull(record.getDischargecountwarnvalue()),
        //             isnull(record.getDischargecountwarnrelievevalue()),
        //             isnull(record.getLastchargecountalarmstatus()), true, "放电次数", record.getDevicegroup(), record.getDeviceaddr(),
        //             record.getPointname()));
        // alarmMessage += GetAlarmMessage(pdsensor.getLastchargecountalarmstatus(), "放电次数");
        // array.add(pdsensor.getLastchargecountalarmstatus());

        alarmLevel = HexUtil.MAX(array);
            pdsensor.setLastalarmlevel(alarmLevel);
            pdsensor.setLastalarmmessage(alarmMessage);
            pdsensor.setLastcommunicationstatus(0);
            //pdsensor.setLastdatatime(new Date());
              Date hisdatatime =null;
            //  for (int i = 0; i < 500; i++) {
            //      updatehis(pdsensor);
            //      }
            pdsensor.setLasthisdatatime(hisdatatime);
            if ( bxsusbpdsensorServiceImpl.Update(pdsensor, false) == 0) {
                setText("更新实时数据失败，请检查数据库连接");
            }
        }
        private Date addHistory(Bxsusbpdsensor sensor) {
            if (sensor != null) {
                if (sensor.getLasthisdatatime() == null) {
                    add(sensor);
                    return new Date();
                } else {
                    long lasttime = 0;
                    long nowtime = 0;
                    try {
                        lasttime = HexUtil.todate(sensor.getLasthisdatatime()).getTime();
                        nowtime = HexUtil.todate(new Date()).getTime();
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    int timersp = 60000;
                    if (sensor.getLastalarmlevel() != 0) {
                        timersp = ad.getHisalarmtimersp()*1000;
                    } else {
                        timersp = ad.getHistimersp()*1000;
                    }
                    if (lasttime + timersp < nowtime) {
                        add(sensor);
                        return new Date();
                    }
                }
            }
            return null;
        }

        private void add(Bxsusbpdsensor sensor) {
            Bxsusbpdhistory his = new Bxsusbpdhistory();
            his.setDeviceaddr(sensor.getDeviceaddr());
            his.setDevicegroup(sensor.getDevicegroup());
            his.setAlarmlevel(sensor.getLastalarmlevel());
            his.setAlarmmessage(sensor.getLastalarmmessage());
            his.setDatatime(sensor.getLastdatatime());
            his.setPointname(sensor.getPointname());
            his.setPointaddr(sensor.getPointaddr());
            his.setStationid(sensor.getStationid());
            //需要添加自己定义的属性
            his.setPhase(sensor.getLastphase());
            his.setChargecount(sensor.getLastchargecount());
            his.setDischargeamount(sensor.getLastdischargeamount());
            //his.setChargeamount2(sensor.getLastchargeamount2());
            bxsusbpdsensorServiceImpl.Add(his);
        }
        private void updatehis(Bxsusbpdsensor sensor) {
            Bxsusbpdhistory his = new Bxsusbpdhistory();
            his.setDeviceaddr(sensor.getDeviceaddr());
            his.setDevicegroup(sensor.getDevicegroup());
            his.setAlarmlevel(sensor.getLastalarmlevel());
            his.setAlarmmessage(sensor.getLastalarmmessage());
            his.setDatatime(sensor.getLastdatatime());
            his.setPointname(sensor.getPointname());
            his.setPointaddr(sensor.getPointaddr());
            his.setStationid(sensor.getStationid());
            //需要添加自己定义的属性
            his.setPhase(sensor.getLastphase());
            his.setChargecount(sensor.getLastchargecount());
            his.setDischargeamount(sensor.getLastdischargeamount());
            //his.setChargeamount2(sensor.getLastchargeamount2());
            bxsusbpdsensorServiceImpl.updatehis(his);
        }
/**
 * 发送便携式局放设备数据消息线程
 * 
 * @param Appdevice 数据库设备参数
 * 
 */        
        @Async("threadPool")
        public void startSendThread(Appdevice Appdevice) throws Exception {
            checkType = "crc16";    //modbus crc校验
            timerFlag = true;   //时间计时器标记

            int timersp = (int) Math.round(Appdevice.getTimersp() * 1000);  //时间间隔
            if(ad.getCommunicationmode()==5)    //通信类型USB通信
            {
            float delay = 2 / (Appdevice.getBaudrate())*1000;   //延迟时间
            timerPd.schedule(new TimerTask() {  //时间定时器入口函数
                 @Override
                 public void run() {    //开始定时间
                    System.out.println("时间到，执行任务 "+ Appdevice.getName());
                    String cstr = "";   //命令字符串
                    Process pro=null;   //定义一个指向Process的指针
                    if (addrindex > Appdevice.getAddrmax() || addrindex < Appdevice.getAddrmin())   //设备地址判断
                        addrindex = Appdevice.getAddrmin();
                    cstr = String.format(Appdevice.getCmd(), String.format("%02X", addrindex));//获取命令字符串
                    try {
                                                        
                        Runtime rt = Runtime.getRuntime();  //返回当前应用程序的Runtime对象，
                        pro=rt.exec(currentPath);   //指示Java虚拟机创建一个子进程执行指定的可执行程序，并返回与该子进程对应的Process对象实例
                        Thread.sleep(40 + (int)delay); //延时
                        if(pro.isAlive())   //对象是否活跃
                        {
                            Thread.sleep(1000); //延时
                        }
                        Thread.sleep(1000); //延时
                        receiveData(cstr); //接收数据

                    } catch (Exception EX) {
                        setText(EX.toString());//异常捕捉打印
                    }
                    reSend[addrindex]++;    //发送状态计数
                    if (reSend[addrindex] > 3) { //发送计数大于3
                    bxsusbpdsensorServiceImpl.UpdateStatus(ad, addrindex,1);    //更新通信状态
                    reSend[addrindex] = 0;
                    addrindex++;
                    }
                    
                    if (timerFlag ==false)
                    timerPd.cancel(); //定时器终止
                 }
             },1000,timersp);

            }


        }

        // @Async("threadPool")
        // public void startReceiveThread(){
        //     isrecv.put(Thread.currentThread().getId(), true);
        //     while (isrecv.get(Thread.currentThread().getId()) != null) {
        //         //这里根据实际协议替换,解析方法recvCrc16;recvSum();
        //         recv();
        //         try {
        //             Thread.sleep(interval);
        //         } catch (InterruptedException e) {
        //             e.printStackTrace();
        //         }
        //     }
        // }



}
